import 'package:flutter_riverpod/flutter_riverpod.dart';

import '../models/vote_model.dart';

class VoteNotifier extends StateNotifier<List<VoteEntity>> {
  VoteNotifier() : super([]) {
    _initializeDefaultVotes();
  }

  static final List<VoteEntity> _defaultVotes = [];

  void _initializeDefaultVotes() {
    final now = DateTime.now();

    _defaultVotes.addAll([
      VoteEntity(
        voteId: 'vote_001',
        description:
            'Golden rape flower fields are in full bloom, filling the air with the scent of spring. ',
        voteCount: 45,
        votedUserIds: [''],
        createdTime: now.subtract(const Duration(days: 7)),
      ),
      VoteEntity(
        voteId: 'vote_002',
        description:
            'Cherries in full bloom with petals dancing in the spring breeze.',
        voteCount: 32,
        votedUserIds: ['user_002'],
        createdTime: now.subtract(const Duration(days: 6)),
      ),
      VoteEntity(
        voteId: 'vote_003',
        description: 'Hop on your bike and ride along the scenic trails.',
        voteCount: 78,
        votedUserIds: ['user_003'],
        createdTime: now.subtract(const Duration(days: 5)),
      ),
      VoteEntity(
        voteId: 'vote_004',
        description: 'Have a special barbecue party in spring!',
        voteCount: 23,
        votedUserIds: ['user_004'],
        createdTime: now.subtract(const Duration(days: 4)),
      ),
      VoteEntity(
        voteId: 'vote_005',
        description: 'Go on an adventure to Zhangjiajie, Hunan.',
        voteCount: 56,
        votedUserIds: ['user_005'],
        createdTime: now.subtract(const Duration(days: 3)),
      ),
      VoteEntity(
        voteId: 'vote_006',
        description:
            'Hike to the mountaintops, fly a kite, or simply relax under the blue sky.',
        voteCount: 41,
        votedUserIds: ['user_006'],
        createdTime: now.subtract(const Duration(days: 2)),
      ),
      VoteEntity(
        voteId: 'vote_007',
        description:
            'Step into the valley of spring, surrounded by peach blossoms bathed in pink hues. ',
        voteCount: 67,
        votedUserIds: ['user_007'],
        createdTime: now.subtract(const Duration(days: 1)),
      ),
      VoteEntity(
        voteId: 'vote_008',
        description:
            'The pink walls, black tiles and rape flowers in the ancient village form a beautiful scenery.',
        voteCount: 29,
        votedUserIds: ['user_008'],
        createdTime: now.subtract(const Duration(hours: 12)),
      ),
    ]);

    state = List.from(_defaultVotes);
  }

  List<VoteEntity> getAllVotes() => List.from(_defaultVotes);

  VoteEntity? getVoteById(String voteId) {
    try {
      return _defaultVotes.firstWhere((vote) => vote.voteId == voteId);
    } catch (e) {
      return null;
    }
  }

  VoteEntity? getUserCurrentVote(String userId) {
    try {
      return _defaultVotes.firstWhere((vote) => vote.hasUserVoted(userId));
    } catch (e) {
      return null;
    }
  }

  Future<bool> vote(String voteId, String userId) async {
    try {
      await Future.delayed(const Duration(milliseconds: 300));

      final previousVoteIndex = _defaultVotes.indexWhere(
        (vote) => vote.hasUserVoted(userId),
      );

      if (previousVoteIndex != -1) {
        final previousVote = _defaultVotes[previousVoteIndex];
        final updatedVotedUserIds =
            previousVote.votedUserIds.where((id) => id != userId).toList();
        final updatedPreviousVote = previousVote.copyWith(
          voteCount: previousVote.voteCount - 1,
          votedUserIds: updatedVotedUserIds,
        );
        _defaultVotes[previousVoteIndex] = updatedPreviousVote;
      }

      final voteIndex = _defaultVotes.indexWhere(
        (vote) => vote.voteId == voteId,
      );
      if (voteIndex == -1) return false;

      final vote = _defaultVotes[voteIndex];
      final updatedVote = vote.copyWith(
        voteCount: vote.voteCount + 1,
        votedUserIds: [...vote.votedUserIds, userId],
      );

      _defaultVotes[voteIndex] = updatedVote;
      state = List.from(_defaultVotes);
      return true;
    } catch (e) {
      return false;
    }
  }

  Future<bool> unvote(String voteId, String userId) async {
    try {
      await Future.delayed(const Duration(milliseconds: 300));

      final voteIndex = _defaultVotes.indexWhere(
        (vote) => vote.voteId == voteId,
      );
      if (voteIndex == -1) return false;

      final vote = _defaultVotes[voteIndex];
      if (!vote.hasUserVoted(userId)) return false;

      final updatedVotedUserIds =
          vote.votedUserIds.where((id) => id != userId).toList();
      final updatedVote = vote.copyWith(
        voteCount: vote.voteCount - 1,
        votedUserIds: updatedVotedUserIds,
      );

      _defaultVotes[voteIndex] = updatedVote;
      state = List.from(_defaultVotes);
      return true;
    } catch (e) {
      return false;
    }
  }
}

final voteProvider = StateNotifierProvider<VoteNotifier, List<VoteEntity>>((
  ref,
) {
  return VoteNotifier();
});

final singleVoteProvider = Provider.family<VoteEntity?, String>((ref, voteId) {
  final voteNotifier = ref.read(voteProvider.notifier);
  return voteNotifier.getVoteById(voteId);
});

final userCurrentVoteProvider = Provider.family<VoteEntity?, String>((
  ref,
  userId,
) {
  ref.watch(voteProvider);
  final voteNotifier = ref.read(voteProvider.notifier);
  return voteNotifier.getUserCurrentVote(userId);
});
